package pprz.light;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.font.GlyphVector;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;

import javax.swing.event.EventListenerList;

public class LightButton extends LightContainer 
implements MouseListener, ImageObserver
{
		static final long serialVersionUID=1;
		static final int labelPadding=3;
		final Color none=new Color(0f,0f,0f,0f);
		int vmargin=3;
		int hmargin=3;
		float valign=0.5f;
		float halign=0.5f;

		boolean showLabel;
		boolean showIcon;
		
		Image default_icon;
		Image mouse_over_icon;
		Image mouse_pressed_icon;
		
		
		Image icon;

		Rectangle bnd;

		Paint default_paint;
		Paint mouse_over_paint;
		Paint mouse_pressed_paint;

		BufferedImage textImage;
		
		EventListenerList listenerList;
		
		public LightButton(String text)
		{
			allocate();
			this.setName(text);
			this.mouse_over_icon=null;
			this.mouse_pressed_icon=null;
			this.default_icon=null;
			initialize();
//			this.setBorder(new LightBorder(new RoundRectangle2D.Float(0,0,1,1,6,6),2));
//			this.setPaintBorder(false);		
			
		}
		
		public LightButton(Image icon)
		{
			allocate();
			showIcon=true;
			this.default_icon=icon;
			this.icon=icon;
			initialize();
//			this.setBorder(new LightBorder(new RoundRectangle2D.Float(0,0,1,1,5,5),1));
//			this.setPaintBorder(false);
//			this.setBorderColor(Color.white);
			
		}

		public LightButton(String text, Image icon)
		{
			allocate();
			this.setName(text);
			showIcon=true;
			this.default_icon=icon;
			this.icon=icon;
			initialize();		
		}

		protected void allocate()
		{
			default_icon=null;
			mouse_over_icon=null;
			mouse_pressed_icon=null;
			icon=null;
			mouse_over_paint=null;
			mouse_pressed_paint=null;
			textImage=null;
			listenerList = new EventListenerList();
			bnd=new Rectangle(0,0,0,0);			
		}
		
		protected void initialize()
		{
//			this.default_paint=this.getBackground();
//			this.mouse_over_paint=this.getBackground();
//			this.mouse_pressed_paint=this.getBackground();
			this.addMouseListener(this);
		}

		public void setVMargin(int v) {vmargin=v;}
		
		public void setHMargin(int h) {hmargin=h;}
		
		public float getAlignmentX(){return halign;}
		
		public float getAlignmentY(){return valign;}
		
		public void setAlignmentX(float x){halign=x;}
		
		public void setAlignmentY(float y){valign=y;}
		
		public void setText(String text) {this.setName(text); showLabel=true; validate(); repaint(100);}
		
/*		@Override
		public Dimension getMinimumSize() {	return bnd.getSize();}

		@Override
		public Dimension getPreferredSize() { return bnd.getSize(); }
*/
		public void validate()
		{
			if (showLabel) { 
				bnd=findNameSize();
				textImage=new BufferedImage(bnd.width,bnd.height,BufferedImage.TYPE_4BYTE_ABGR);
				Graphics2D g=textImage.createGraphics();
				g.setRenderingHint (RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
				g.setRenderingHint (RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
				g.setColor(new Color(0f,0f,0f,0f));
				g.fillRect(0, 0, bnd.width, bnd.height);
				GlyphVector gv=g.getFont().createGlyphVector(g.getFontRenderContext(), getName());
				Shape v=gv.getOutline(0, g.getFontMetrics().getAscent());
				g.setColor(this.getForeground());
				g.fill(v);
				g.dispose();
			}
			else bnd.setRect(0, 0, 0, 0);
			if (showIcon && default_icon!=null) {
				int h=default_icon.getHeight(this);
				int w=default_icon.getWidth(this);
				if (mouse_over_icon!=null) {
					w=w>mouse_over_icon.getWidth(this)?w:mouse_over_icon.getWidth(this);
					h=h>mouse_over_icon.getHeight(this)?h:mouse_over_icon.getHeight(this);
				}
				if (mouse_pressed_icon!=null) {
					w=w>mouse_pressed_icon.getWidth(this)?w:mouse_pressed_icon.getWidth(this);
					h=h>mouse_pressed_icon.getHeight(this)?h:mouse_pressed_icon.getHeight(this);
				}

				bnd.setSize(	bnd.width>w?
								bnd.width:w, 
								bnd.height+h);
			}
			bnd.grow(hmargin*2, vmargin*2);
			if (showLabel && showIcon) bnd.grow(0,labelPadding);
//			System.out.println("validate--LightButton");
			super.validate();
		}
		
		
		
		
		protected Rectangle findNameSize()
		{
			// find out text line dimensions with current font
			GraphicsEnvironment ge = GraphicsEnvironment.
            getLocalGraphicsEnvironment();
			BufferedImage dbImage = new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB); 
			Graphics2D g=ge.createGraphics(dbImage);
			FontMetrics f=g.getFontMetrics();
			Rectangle border=f.getStringBounds(getName(), g).getBounds();
			g.dispose();
			return border;
		}
		
		public void setDefaultPaint(Paint paint)
		{this.default_paint=paint; validate(); repaint(100);}
		
		public void setMouseOverPaint(Paint paint)
		{this.mouse_over_paint=paint; validate(); repaint(100);}

		public void setMousePressedPaint(Paint paint)
		{this.mouse_pressed_paint=paint; validate(); repaint(100);}

		public void setDefaultIcon(Image im)
		{this.default_icon=im; im.getHeight(this); validate(); repaint(100);}
		
		public void setMouseOverIcon(Image im)
		{this.mouse_over_icon=im; im.getHeight(this); validate(); repaint(100);}

		public void setMousePressedIcon(Image im)
		{this.mouse_pressed_icon=im; im.getHeight(this); validate(); repaint(100);}

		@Override
		public void setBackground(Color c) {
			default_paint=c;
			super.setBackground(c);
		}

		@Override
		public void draw(Graphics g) {
			super.draw(g);
//			Graphics2D g2=(Graphics2D)g;
//			g2.setPaint(paint);
//			g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			
			if (showIcon && icon!=null) {
				int x, y;
				x=Math.round((this.getWidth()-icon.getWidth(this))*halign);
				if (showLabel) y=Math.round((this.getHeight()-textImage.getHeight()-LightButton.labelPadding-icon.getHeight(this))*valign);
				else  y=Math.round((this.getHeight()-icon.getHeight(this))*valign);
				g.drawImage(icon, x, y, this);
			}
			if (showLabel)
			{
				int x, y;
				x=Math.round((this.getWidth()-textImage.getWidth())*halign);
				if (icon!=null) y=Math.round((
						this.getHeight()
						-textImage.getHeight()
						+LightButton.labelPadding
						+icon.getHeight(this)
						)*valign);
				else  y=Math.round((
						this.getHeight()
						-textImage.getHeight()
						)*valign);
				g.drawImage(textImage, x, y, null);
			}
		}
		
		public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h)
		{
			if ((infoflags&ImageObserver.ALLBITS)!=0)
			{
				validate();
				repaint(100);
				//System.out.println("got image!");
				return false;
			}
			return true;
		}
		
		
		public void mouseEntered(MouseEvent arg0) {
			if (this.isEnabled()) {
				if (mouse_over_icon!=null) icon=mouse_over_icon;
				else icon=default_icon;
				if (mouse_over_paint!=null) setBackgroundPaint(mouse_over_paint);
				else setBackgroundPaint(default_paint);
				validate();
				repaint(100);
			}
		}
		
		public void mouseExited(MouseEvent arg0) {
			if (this.isEnabled()) {			
				icon=default_icon;
				setBackgroundPaint(default_paint);
				validate();
				repaint(100);
			}
		}
		
		public void mouseClicked(MouseEvent arg0) {}
		public void mousePressed(MouseEvent arg0) 
		{
			if (this.isEnabled()) {
				if (mouse_pressed_icon!=null) icon=mouse_pressed_icon;
				else icon=default_icon;
				if (mouse_pressed_paint!=null) setBackgroundPaint(mouse_pressed_paint);
				else setBackgroundPaint(default_paint);
				validate();
				repaint(100);
			}
		}
		public void mouseReleased(MouseEvent arg0) 
		{
			if (this.isEnabled()) {
				if (this.contains(arg0.getPoint())) 
				{
					mouseEntered(arg0);
					fireActionEvent(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,this.getName()));					
				}
				else {
					icon=default_icon;
					setBackgroundPaint(default_paint);
					validate();
					repaint(100);
				}
			}			
		}

	   // These methods allows classes to register for events
	    public void addActionEventListener(ActionListener listener) {
	        listenerList.add(ActionListener.class, listener);
	    }
	    
	    // This methods allows classes to unregister for events
	    public void removeActionEventListener(ActionListener listener) {
	        listenerList.remove(ActionListener.class, listener);
	    }
	    
	    // This protected class is used to fire events
	    protected void fireActionEvent(ActionEvent evt) {
	        Object[] listeners = listenerList.getListenerList();
	        // Each listener occupies two elements - the first is the listener class
	        // and the second is the listener instance
	        for (int i=0; i<listeners.length; i+=2) {
	            if (listeners[i]==ActionListener.class) {
	                ((ActionListener)listeners[i+1]).actionPerformed(evt);
	            }
	        }
	    }		
		
}
